package org.tio.sitexxx.web.server.controller.base;

import java.util.Date;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.http.common.HttpConfig;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.http.common.session.HttpSession;
import org.tio.http.server.annotation.RequestPath;
import org.tio.http.server.util.Resps;
import org.tio.sitexxx.service.model.main.*;
import org.tio.sitexxx.service.service.base.IpInfoService;
import org.tio.sitexxx.service.service.base.LoginLogService;
import org.tio.sitexxx.service.service.base.UserService;
import org.tio.sitexxx.service.service.base.UserTokenService;
import org.tio.sitexxx.service.vo.RequestExt;
import org.tio.sitexxx.service.vo.SessionExt;
import org.tio.sitexxx.service.vo.SessionKey;
import org.tio.sitexxx.web.server.utils.WebUtils;
import org.tio.sitexxx.web.server.vo.LoginResult.ErrorCode;
import org.tio.utils.SystemTimer;
import org.tio.utils.crypto.ACEUtils;
import org.tio.utils.jfinal.P;
import org.tio.utils.resp.Resp;

import com.jfinal.kit.Ret;

import cn.hutool.core.util.StrUtil;

/**
 * @author tanyaowu
 * 2016年6月29日 下午7:53:59
 */
@RequestPath(value = "/login")
public class LoginController {
	private static Logger log = LoggerFactory.getLogger(LoginController.class);

	/**
	 * @param args
	 * @author tanyaowu
	 */
	public static void main(String[] args) {

	}

	private UserService userService = UserService.ME;

	/**
	 *
	 * @author tanyaowu
	 */
	public LoginController() {
	}

	/**
	 * @param loginname
	 * @param pwd
	 * @param pd5 md5加密的密码
	 * @param authcode
	 * @param request
	 * @return
	 */
	private Ret _login(String loginname, String pwd, String pd5, String authcode, HttpRequest request) {
		Ret ret = null;
		ret = userService.login(loginname, pwd, pd5);
		if (ret.isFail()) {
			Resp resp = Resp.fail();

			Integer code = (Integer) ret.get("code");
			if (code == 3) {
				resp.code(3);
			} else {
				resp.code(ErrorCode.USER_OR_PWD_ERROR_PWD.code).msg(ErrorCode.USER_OR_PWD_ERROR_PWD.value);
			}

			HttpResponse httpResponse = Resps.json(request, resp);
			return Ret.fail().set("resp", httpResponse);//.fail(ErrorCode.USER_OR_PWD_ERROR, httpResponse);
		} else {
			User user = (User) ret.get("user");
			Resp resp = checkStatus(user);
			if (resp.isOk()) {
				return Ret.ok().set("user", user);
			} else {
				HttpResponse httpResponse = Resps.json(request, resp);
				return Ret.fail().set("resp", httpResponse);
			}
		}
	}

	private static Resp checkStatus(User user) {
		if (Objects.equals(user.getStatus(), org.tio.sitexxx.service.model.main.User.Status.NORMAL)) {
			return Resp.ok();
		} else {
			if (Objects.equals(user.getStatus(), org.tio.sitexxx.service.model.main.User.Status.INBLACK)) {
				return Resp.fail().code(ErrorCode.USER_INBLACK_ERROR.code).msg(ErrorCode.USER_INBLACK_ERROR.value);
			} else {
				return Resp.fail().code(ErrorCode.USER_STATUS_ERROR.code).msg(ErrorCode.USER_STATUS_ERROR.value);
			}
		}
	}

	/**
	 * http://127.0.0.1/login?loginname=tywo45@163.com&pwd=c68fd49a78b33a0199bed7b6c8953953&pd5=fidksjfdlskfjdks
	 * 登录，这个是公共的，具体实现是在_login中
	 * @param loginname
	 * @param pwd
	 * @param pd5 md5加密后的密码
	 * @param authcode 图形验证码
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@RequestPath(value = "")
	public HttpResponse login(String loginname, String pwd, String pd5, String authcode, HttpRequest request) throws Exception {
		System.out.println("loginname:"+loginname+"pwd:"+pwd+"pd5:"+pd5+"authcode:"+authcode+"request:"+request.toString());
		loginname = StrUtil.trim(loginname);
		User t = UserService.ME.getByLoginname(loginname,null);
		pd5 = t.getPwd();
		if (StrUtil.isNotBlank(pwd)) {
			String pwdKey = P.get("pwd.key.login.aes");
			pwd = ACEUtils.decrypt(pwd, pwdKey, pwdKey);
		}

		String sessionId = request.getHttpSession().getId();
		System.out.println(sessionId+"sessionid");

		User user = null;//WebUtils.currUser(request);

		HttpSession httpSession = request.getHttpSession();
		HttpConfig httpConfig = request.getHttpConfig();

		Ret ret = this._login(loginname, pwd, pd5, authcode, request);
		if (ret.isOk()) {
			user = (User) ret.get("user");

			RequestExt requestExt = WebUtils.getRequestExt(request);

			//添加登录日志
			String ip = request.getClientIp();
			IpInfo ipinfo = IpInfoService.ME.save(ip);
			LoginLog loginLog = new LoginLog();
			loginLog.setIp(ip);
			loginLog.setIpid(ipinfo.getId());
			loginLog.setSessionid(sessionId);
			loginLog.setUid(user.getId());
			loginLog.setTime(new Date());

			UserAgent userAgent = requestExt.getUserAgent();
			if (userAgent != null) {
				if (userAgent.getId() != null) {
					loginLog.setUaid(userAgent.getId());
				}
			}

			LoginLogService.me.add(loginLog);

			//token
			UserToken userToken = UserTokenService.me.findFirst(user.getId());
			if (userToken == null) {
				userToken = new UserToken();
				userToken.setUid(user.getId());
				userToken.setToken(sessionId);
				UserTokenService.me.add(userToken);
			} else {
				String oldToken = userToken.getToken();
				if (Objects.equals(oldToken, sessionId)) {
					//这里是自己T自己，相当于没T
				} else {
					//把原来别人登录的T出去
					HttpSession oldHttpSession = (HttpSession) httpConfig.getSessionStore().get(oldToken);
					if (oldHttpSession != null) {
						SessionExt oldSessionExt = oldHttpSession.getAttribute(SessionKey.SESSION_EXT, SessionExt.class, new SessionExt(), httpConfig);
						oldSessionExt.setUid(null);
						oldSessionExt.setKickedInfo(loginLog);
						oldHttpSession.update(httpConfig);//切记：每次修改SessionExt后，要调用一下update把数据更新到分布式缓存中
					}
					userToken.setToken(sessionId);
					UserTokenService.me.update(userToken);
				}
			}

			//
			SessionExt sessionExt = httpSession.getAttribute(SessionKey.SESSION_EXT, SessionExt.class);
			sessionExt.setUid(user.getId());
			sessionExt.setLoginTime(SystemTimer.currTime);
			httpSession.update(httpConfig);//切记：每次修改SessionExt后，要调用一下update把数据更新到分布式缓存中

			Resp resp = Resp.ok();//.data(map);
			HttpResponse httpResponse = Resps.json(request, resp);
			return httpResponse;
		} else {
			HttpResponse httpResponse = (HttpResponse) ret.get("resp");
			if (httpResponse == null) {
				log.error("_login(loginname, pwd, authcode, request)返回值没有包含response信息");
				return Resps.json(request, Resp.fail("服务器异常"));
			}
			return httpResponse;
		}
	}
}
